with ada.Strings; use ada.strings;

package body ariane.maths.matrix.any is

  -- returns an object created with specified size filled with zeros
  function create(m, n : positive) return object is
    data : data_t(1..m, 1..n) := (others=>(others=>zero));
    res : object(m, n);
  begin
    set(res, data);
    return res;
  end create;

  -- returns an object created and initialized with given data
  function create(data : data_t) return object is
    res : object(data'Length(1), data'Length(2));
  begin
    set(res, data);
    return res;
  end create;

  -- initializes an object with given data
  procedure set(o : in out object; data : data_t) is
  begin
    o.data := data;
  end set;

  -- sets value for the specific component in a matrix objects
  procedure set(o : in out object; i, j : positive; val : component_t) is
  begin
    o.data(i,j) := val;
  end set;


  -- gets value of the specific component in a matrix object
  function get(o : object; i, j : positive) return component_t is
  begin
    return o.data(i,j);
  end get;

    -- returns number of rows of the matrix
  function numrows(o : object) return positive is
  begin
    return o.data'Length(1);
  end numrows;

  -- returns number of columns of the matrix
  function numcols(o : object) return positive is
  begin
    return o.data'Length(2);
  end numcols;

  -- returns the sum of two matrix objects of same dimensions
  function "+"(lhs, rhs : object) return object is
    res : object(lhs.m, lhs.n);
  begin
    for i in 1..rhs.m loop
      for j in 1..rhs.n loop
        res.data(i,j) := lhs.data(i,j) + rhs.data(i,j);
      end loop;
    end loop;
    return res;
  end "+";

  -- returns the difference of two matrix objects of same dimensions
  function "-"(lhs, rhs : object) return object is
    res : object(lhs.m, lhs.n);
  begin
    for i in 1..res.m loop
      for j in 1..res.n loop
        res.data(i,j) := lhs.data(i,j) - rhs.data(i,j);
      end loop;
    end loop;
    return res;
  end "-";

  -- returns the product of two multipliable matrix objects
  function "*"(lhs, rhs : object) return object is
    res : object(lhs.m, rhs.n);
  begin
    for i in 1..lhs.m loop
      for j in 1..rhs.n loop
        res.data(i,j) := zero;
        for k in 1..lhs.n loop
          res.data(i,j) := res.data(i,j) + lhs.data(i,k) * rhs.data(k,j);
        end loop;
      end loop;
    end loop;
    return res;
  end "*";

  -- returns the negative of a matrix object
  function "-"(o : object) return object is
    res : object(o.m, o.n);
  begin
    for i in 1..res.m loop
      for j in 1..res.n loop
        res.data(i,j) := -o.data(i,j);
      end loop;
    end loop;
    return res;
  end "-";

end ariane.maths.matrix.any;
